import * as THREE from 'three';
// 粒子系统
export default class {
  particleList = [];
  emitRate = 0;
  emitTime = 0;
  maxCount = 0;
  emitAreaRotateMatrix;
  geometry;
  particleMaterial: any;
  instancedMesh: any;
  planeGeometry: any;
  config: any;
  disposeList: any[];
  context: any;
  scale = new THREE.Vector3();
  position = new THREE.Vector3();
  rotation = new THREE.Euler();
  constructor() {
    this.disposeList = [];
    this.particleList = [];
    this.emitRate = 0;
    this.emitTime = 0;
    this.maxCount = 0;
    this.emitAreaRotateMatrix = new THREE.Matrix4();
    this.geometry = new THREE.BufferGeometry();
    this.particleMaterial = null;
    this.instancedMesh = null;
    this.planeGeometry = new THREE.PlaneGeometry(1, 1);
  }
  onRefresh() {
    var e = this.config;
    var t = e.basic;
    var n = e.emit;
    var a = n.rate;
    var i = n.area;
    this.onDestroy();
    this.emitRate = a / 1e3;
    this.maxCount = t.maxCount;
    this.emitAreaRotateMatrix = new THREE.Matrix4();
    this.emitAreaRotateMatrix.makeRotationFromEuler(i.rotate.x, i.rotate.y, i.rotate.z);
    var r = t.transform;
    var o = r.translate;
    var s = r.rotation;
    var l = r.scale;
    this.position.set(o.x, o.y, o.z);
    this.rotation.set(s.x, s.y, s.z);
    this.scale.set(l.x, l.y, l.z);
    var u = this.context.assetsMgr.getTextureImage(t.texture);
    var c = new me(u);
    c.needsUpdate = true;
    var material = new THREE.ShaderMaterial({
      uniforms: {
        map: {
          value: c
        }
      },
      vertexShader: `
        precision highp float;
        uniform mat4 modelViewMatrix;
        uniform mat4 projectionMatrix;
        uniform mat3 normalMatrix;
        uniform mat4 viewMatrix;
        uniform mat4 modelMatrix;
        
        attribute mat4 instanceMatrix;
        attribute vec3 instanceColor;
        attribute vec3 position;
        attribute vec2 uv;
        attribute float opacity;
        
        varying vec3 vColor;
        varying vec2 vUv;
        varying float vOpacity;
        
        void main() {
          vUv = uv;
          vColor = instanceColor;
          vOpacity=opacity;
          mat4 resetMatrix=mat4(viewMatrix*modelMatrix*instanceMatrix);
          resetMatrix[0][0] = instanceMatrix[0][0];
          resetMatrix[0][1] = 0.0;
          resetMatrix[0][2] = 0.0;
          resetMatrix[1][0] = 0.0;
          resetMatrix[1][1] = instanceMatrix[1][1];
          resetMatrix[1][2] = 0.0;
          resetMatrix[2][0] = 0.0;
          resetMatrix[2][1] = 0.0;
          resetMatrix[2][2] = instanceMatrix[2][2];
          gl_Position = projectionMatrix * resetMatrix * vec4( position, 1.0 );
        }
      `,
      fragmentShader: `
        precision highp float;
        uniform sampler2D map;
        varying vec2 vUv;
        varying vec3 vColor;
        varying float vOpacity;
        void main() {
          vec4 diffuseColor = texture2D( map, vUv );
          gl_FragColor = diffuseColor*(vColor,vOpacity);
          gl_FragColor*=vec4(vColor,vOpacity);
        }
      `,
      blending: 2,
      depthTest: false,
      transparent: true
    });
    this.disposeList.push(material);
    this.particleMaterial = material;
  }
  onDestroy() {
    this.clear();
    this.geometry.dispose();
    this.planeGeometry.dispose();
    this.particleList = [];
  }
  clear() {}
  emit() {
    var e = this.config;
    var t = e.basic;
    var n = t.lifeTime;
    var a = (t.start, t.end, e.emit.area);
    var i = vc(a.x);
    var r = vc(a.y);
    var o = vc(a.z);
    if ('球形' == a.shape) {
      var s = Math.random() * Math.PI * 2;
      var l = Math.random() * Math.PI;
      i = i * Math.sin(l) * Math.cos(s);
      r = r * Math.sin(l) * Math.sin(s);
      o *= Math.cos(l);
    } else if ('圆形' == a.shape) {
      var u = Math.random() * Math.PI * 2;
      i *= Math.cos(u);
      r *= Math.sin(u);
      var c = new _e(i, r, (o = 0));
      c.applyMatrix4(this.emitAreaRotateMatrix);
      i = c.x;
      r = c.y;
      o = c.z;
    }
    var h = new mc(1e3 * vc(n, true), this.config);
    this.particleList.push(h);
    h.setPosition(i, r, o);
  }
  onUpdate(e) {
    this.updateEmit(e);
    this.updateParticles(e);
  }
  updateEmit(e) {
    if (this.particleList.length < this.maxCount) {
      this.emitTime = e;
      var t = this.emitRate * this.emitTime;
      if (t > this.maxCount) {
        t = this.maxCount - this.particleList.length;
        if (t > 1) {
          for (var n = 1; n <= t; n++) {
            this.emit();
          }
        }
        this.emitTime = 0;
      }
    } else {
      this.emitTime = 0;
    }
  }
  add(e) {
    this.instancedMesh.add(e);
  }
  remove(e) {
    this.removeParticle(e);
  }
  updateParticles(e) {
    var t = this.particleList;
    this.geometry.dispose();
    if (this.instancedMesh) {
      this.remove(this.instancedMesh);
    }
    var n = new THREE.BufferGeometry();
    n.index = this.planeGeometry.index;
    var a = new Float32Array(t.length);
    n.attributes = this.planeGeometry.attributes;
    this.geometry = n;
    var i;
    var r = new THREE.Mesh(this.planeGeometry, this.particleMaterial);
    this.add(r);
    this.instancedMesh = r;
    for (var o = 0; o < t.length; o++) {
      i = t[o];
      i.update(e);
      if (i.isDead) {
        this.removeParticle(i);
        o--;
      } else {
        var s = new Qe();
        s.compose(i.position, i.rotation, i.scale);
        r.setMatrixAt(o, s);
        r.setColorAt(o, i.color);
        a[o] = i.opacity;
      }
    }
    n.setAttribute('opacity', new Rr(a, 1));
  }
  removeParticle(e) {
    this.particleList.splice(this.particleList.indexOf(e), 1);
  }
}
